<?php
namespace App\GraphQL\Mutations\Group;

use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use App\Models\GroupPolicy;
use App\Models\GroupPolicyRule;

class CreatePolicy
{

    /**
     * Return a value for the field.
     *
     * @param null $rootValue
     *            Usually contains the result returned from the parent field. In this case, it is always `null`.
     * @param mixed[] $args
     *            The arguments that were passed into the field.
     * @param \Nuwave\Lighthouse\Support\Contracts\GraphQLContext $context
     *            Arbitrary data that is shared between all fields of a single query.
     * @param \GraphQL\Type\Definition\ResolveInfo $resolveInfo
     *            Information about the query itself, such as the execution state, the field name, path to the field from the root, and more.
     * @return mixed
     */
    public function __invoke($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
    {
        $data = $args['input'];
        $authUser = auth()->user();
        $this->validate($data);
        $distributors = collect($data['distributors'])->map(function ($item, $index) {
            $item['sort'] = $index;
            $item['cate'] = 'DISTRIBUTOR';
            $item['scale'] = intval($item['scale'] * 100);
            return $item;
        });
        $merchants = collect($data['merchants'])->map(function ($item, $index) {
            $item['sort'] = $index;
            $item['cate'] = 'MERCHANT';
            $item['scale'] = intval($item['scale'] * 100);
            return $item;
        });
        $staffs = collect($data['staffs'])->map(function ($item, $index) {
            $item['sort'] = $index;
            $item['cate'] = 'STAFF';
            $item['scale'] = intval($item['scale'] * 100);
            return $item;
        });
        $deviceRules = $distributors->concat($merchants);
        if ($deviceRules->sum('scale') > 10000) {
            throw new \Exception('设备分组分成比例不能超过100%');
        }
        if($merchants->count() > 1) {
            throw new \Exception('终端伙伴只能有一个!');
        }
        if ($staffs->sum('scale') > 10000) {
            throw new \Exception('分润员工分成比例不能超过100%');
        }
        $allRules = $deviceRules->concat($staffs)->map(function($item){
            return new GroupPolicyRule($item);
        });
        // 创建策略
        $policy = GroupPolicy::create([
            'name'=>$data['name'],
            'cate'=>$data['cate'],
            'resource_cate'=>$data['resource_cate'],
            'user_id'=>$authUser->id
        ]);
        $policy->rules()->saveMany($allRules);
        // 保存规则
        return [
            'status' => '200',
            'message' => '创建成功'
        ];
    }

    public function validate($data)
    {
        $authUser = auth()->user();
        $cates = [
            'DEVICE'
        ];
        if ($authUser->role_code == 'MERCHANT') {
            $cates = [
                'STAFF'
            ];
        }
        $rules = [
            'name' => [
                'required',
                'max:18'
            ],
            'cate' => [
                'required',
                Rule::in($cates)
            ],
            'resource_cate' => [
                'required',
                Rule::in([
                    'CURRENT',
                    'CUSTOM'
                ])
            ],
            'distributors' => [
                'nullable',
                'array'
            ],
            'merchants' => [
                'nullable',
                'array'
            ],
            'staffs' => [
                'nullable',
                'array'
            ],
            'distributors.*.name' => [
                'required'
            ],
            'distributors.*.scale' => [
                'required',
                'numeric',
                'min:0',
                'max:10000'
            ],
            'merchants.*.name' => [
                'required'
            ],
            'merchants.*.scale' => [
                'required',
                'numeric',
                'min:0',
                'max:100'
            ],
            'staffs.*.name' => [
                'required'
            ],
            'staffs.*.scale' => [
                'required',
                'numeric',
                'min:0',
                'max:100'
            ]
        ];
        $messages = [
            'name.required' => '名称不能为空',
            'name.max' => '名称不能超过18个字',
            'cate.required' => '分类不能为空',
            'resource_cate.required' => '内容分组不能为空',
            'resource_cate.in' => '内容分组不能超出限制',
            'cate.in' => '分类不能超出限制',
            'distributors.array' => '分销商规则为数组',
            'merchants.array.required' => '终端伙伴规则为数组',
            'distributors.*.name.required' => '分销商规则名称不能为空',
            'merchants.*.name.required' => '终端伙伴规则名称不能为空',
            'staffs.*.name.required' => '分润员工规则名称不能为空',
            'distributors.*.scale.required' => '分销商规则比例不能为空',
            'merchants.*.scale.required' => '终端伙伴规则比例不能为空',
            'staffs.*.scale.required' => '分润员工规则比例不能为空',
            'distributors.*.scale.numeric' => '分销商规则比例为数字',
            'merchants.*.scale.numeric' => '终端伙伴规则比例为数字',
            'staffs.*.scale.numeric' => '分润员工规则比例为数字',
            'distributors.*.scale.min' => '分销商规则比例不能为负数',
            'merchants.*.scale.min' => '终端伙伴规则比例不能为负数',
            'staffs.*.scale.min' => '分润员工规则比例为不能为负数',
            'distributors.*.scale.max' => '分销商规则比例不能大于100%',
            'merchants.*.scale.max' => '终端伙伴规则比例不能大于100%',
            'staffs.*.scale.max' => '分润员工规则比例不能大于100%'
        ];
        $validate = Validator::make($data, $rules, $messages);
        if ($validate->fails()) {
            throw new \InvalidArgumentException($validate->messages()->first());
        }
        return true;
    }
}
